﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;

namespace AutoBuildVersion.Helper
{
    public static class VersionChanger
    {
        private static readonly int incParamNum = 0;
        private static string _fileName = "";
        private static string _versionStr;
        private static string _titleStr;
        //使用command变量保存全局命令字符串，原先的传递args暂不删除
        private static string _command = "";

        public static List<string> CommitFile;

        public static void ChangeVersion(string path)
        {
            MainWindow.GetWindow()
                .rtbMainDescription.AppendText("======================================================" + "\r\n");
            MainWindow.GetWindow().rtbMainDescription.AppendText("开始更新文件版本号 ..." + "\r\n");
            MainWindow.GetWindow()
                .rtbMainDescription.AppendText("======================================================" + "\r\n");
            var root = new DirectoryInfo(path).Parent;

            if (root == null || !root.Exists)
            {
                MessageBox.Show(Application.Current.MainWindow, "项目目录不存在！");
                return;
            }

            GetFiles(path, false); //更改入口程序的版本号
            var rootdir = Directory.GetDirectories(root.FullName); //获取项目根目录
            foreach (var dir in rootdir)
            {
                GetFiles(dir);
            }
            MainWindow.GetWindow().rtbStepDescription.AppendText("-->" + "更新文件版本号成功 √" + "\r\n");
        }

        /// <summary>
        ///     获取目标路径下的所有需要修改的文件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="needPix"></param>
        private static void GetFiles(string path, bool needPix = true)
        {
            var curDirectory = new DirectoryInfo(path);

            if (needPix)
            {
                if (!(curDirectory.Exists && curDirectory.Name.ToLower().Contains("zillion")))
                    return;
            }


            var strDirectories = Directory.GetDirectories(path);
            var propertiesdir =
                strDirectories.Select(x => new DirectoryInfo(x)).FirstOrDefault(y => y.Name == "Properties");


            if (propertiesdir != null)
            {
                var strFileNames = Directory.GetFiles(propertiesdir.FullName);

                foreach (var strFileName in strFileNames)
                {
                    if (strFileName.Contains("AssemblyInfo.cs"))
                    {
                        SetVersion(strFileName, MainWindow.GetWindow().AssemblyVersion,
                            MainWindow.GetWindow().AssemblyTitle);
                    }
                }
            }


            foreach (var strDirectory in strDirectories)
            {
                GetFiles(strDirectory);
            }
        }

        private static void SetVersion(string assemblyFilePath, string version, string assemblyTitle)
        {
            _fileName = assemblyFilePath;
            _versionStr = version;
            _titleStr = assemblyTitle;

            if (!File.Exists(_fileName))
            {
                MainWindow.GetWindow()
                    .rtbMainDescription.AppendText("Error: Can not find file \"" + _fileName + "\"" + "<--" + "\r\n");
                return;
            }

            MainWindow.GetWindow().rtbMainDescription.AppendText("-->" + "Processing \"" + _fileName + "\"..." + "\r\n");
            var reader = new StreamReader(_fileName);
            var writer = new StreamWriter(_fileName + ".out");
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                line = ProcessLine(line);
                writer.WriteLine(line);
            }
            reader.Close();
            writer.Close();

            File.Delete(_fileName);
            File.Move(_fileName + ".out", _fileName);

            Console.WriteLine("Done!");
        }

        private static string ProcessLine(string line)
        {


            if (_versionStr.IsNotNullOrEmpty())
            {
                line = ProcessVersionLinePart(line, "[assembly: AssemblyVersion(\"");
                line = ProcessVersionLinePart(line, "[assembly: AssemblyFileVersion(\"");
            }
            if (_titleStr.IsNotNullOrEmpty())
            {
                line = ProcessTitleLinePart(line, "[assembly: AssemblyTitle(\"");
            }
           
            return line;
        }

        private static string ProcessVersionLinePart(string line, string part)
        {
            var spos = line.IndexOf(part);
            if (spos >= 0)
            {
                spos += part.Length;
                var epos = line.IndexOf('"', spos);
                var oldVersion = line.Substring(spos, epos - spos);
                var newVersion = "";
                var performChange = false;

                if (incParamNum > 0)
                {
                    var nums = oldVersion.Split('.');
                    if (nums.Length == 4)
                    {
                        newVersion = nums[0];
                        for (var i = 1; i < nums.Length; i++)
                        {
                            newVersion += "." + nums[i];
                        }
                        performChange = true;
                    }
                }
                else if (_versionStr != null)
                {
                    newVersion = _versionStr;
                    performChange = true;
                }

                if (performChange)
                {
                    var str = new StringBuilder(line);
                    str.Remove(spos, epos - spos);
                    str.Insert(spos, newVersion);
                    line = str.ToString();
                }
            }
            return line;
        }

        private static string ProcessTitleLinePart(string line, string part)
        {
            var spos = line.IndexOf(part);
            if (spos < 0) return line;

            spos += part.Length;
            var epos = line.IndexOf('"', spos);
            //var oldVersion = line.Substring(spos, epos - spos);
            var str = new StringBuilder(line);
            str.Remove(spos, epos - spos);
            str.Insert(spos, _titleStr);

            return str.ToString(); ;
        }
    }
}